package org.xtext.runtime.plan;

import is.lill.acre.message.ACREAgentIdentifier;
import is.lill.acre.message.ACREMessage;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.xtext.runtime.formula.Predicate;
import org.xtext.runtime.interpreter.Agent;
import org.xtext.runtime.messaging.AstraMessage;
import org.xtext.runtime.term.ITerm;
import org.xtext.runtime.term.Term;
import org.xtext.runtime.term.Variable;
import org.xtext.runtime.util.Bindings;
import org.xtext.runtime.util.EvaluateTermsVisitor;

/**
 * Plan Step implementation for starting / stopping teleoreactive plans
 *  
 * @author rem
 *
 */
public class SendStep implements IPlanStep {
	String performative;
	ITerm receiver; 
	Predicate content;
	
	public SendStep(String performative, ITerm agent, Predicate content) {
		this.performative = performative;
		this.receiver = agent;
		this.content = content;
	}
	
	@Override
	public String toString(String string) {
		return string + "send(" + performative + "," + receiver + "," + content + ")";
	}

	@Override
	public String toFullString(String string) {
		return toString(string);
	}

	@Override
	public Set<Variable> variables() {
		Set<Variable> variables = new HashSet<Variable>();
		variables.addAll(content.variables());
		return variables;
	}

	@Override
	public void handle(Agent agent, PlanStack planStack) {
		AstraMessage message = new AstraMessage();
		EvaluateTermsVisitor visitor = new EvaluateTermsVisitor(agent);
		String r = (String) ((ITerm) receiver.accept(visitor)).value();
		Predicate c = (Predicate) content.accept(visitor);
		message.setPerformative(performative);
		message.getReceivers().add(r);
		message.setSender(agent.name());
		message.setContent( c );
		if ( agent.getConversationManager() != null ) {
			ACREMessage m = new ACREMessage();
			m.setPerformative(performative);
			m.setReceiver(new ACREAgentIdentifier( r ) );
			m.setSender(agent.getAcreIdentifier());
			m.setContent(c.toString());
			m.setLanguage("ASTRA");
			agent.getConversationManager().processMessage(m);
		}
		agent.messageService().send(message);
		agent.logAction("send(\"" + message.performative() + "\",\"" + message.getReceivers().get(0) + "\"," + message.content() + ")");
	}

	@Override
	public SendStep copy(Map<String, Variable> vars) {
		return new SendStep(performative, receiver.copy(vars), content.copy(vars));
	}

	@Override
	public SendStep apply(Bindings bindings) {
		receiver.apply(bindings);
		content.apply(bindings);
		return this;
	}

	@Override
	public void reset() {
	}
}
